# -*- coding:utf-8 -*-
from bson import ObjectId

__author__ = 'tsdykj'

import sys

sys.path.append('..')
from mongoer import dbobjects

from whoosh_helper import pdf_whoosh
import json
from bson import json_util
from bson.objectid import ObjectId
from flask import Flask, request, Response, render_template, redirect, url_for, flash
from flask_bootstrap import Bootstrap
from flask_flatpages import FlatPages
from flask_login import LoginManager, login_user, current_user, login_required, logout_user, UserMixin
from paginator import *
from os import path, sep
from crossdomain import *

DEBUG = True
FLATPAGES_AUTO_RELOAD = DEBUG
FLATPAGES_EXTENSION = '.md'

login_manager = LoginManager()


def create_app():
    app = Flask(__name__)
    Bootstrap(app)
    app.config.from_object('fileconfig')
    return app


app = create_app()
pages = FlatPages(app)
login_manager.setup_app(app)

num_posts_per_page = dbobjects.settings.find_one({'name': 'post_per_page'})['value']


class user(UserMixin):
    def __init__(self, dbuser):
        self.dbuser = dbuser

    def get_id(self):
        return str(self.dbuser['_id'])


@login_manager.user_loader
def load_user(userid):
    pdfuser = dbobjects.pdfusers.find_one({'_id': ObjectId(userid)})
    return user(pdfuser)


@app.route("/login/", methods=['POST', 'GET'])
def login():
    error = []
    if request.method == 'POST':
        username = request.form['username']
        pwd = request.form['password']

        pdfuser = dbobjects.pdfusers.find_one({'username': username})

        if pdfuser:
            if pdfuser['password'] == pwd:
                login_user(user(pdfuser))
                return redirect(url_for('index'))
            else:
                error.append(u'请输入正确的密码')
        else:
            error.append(u'用户不存在')

    notice_left = ''
    notice_right = ''

    notice = dbobjects.notices.find_one({})

    if notice:
        notice_left = notice['notice_left']
        notice_right = notice['notice_right']

    return render_template('login.html', error=error, notice_left=notice_left, notice_right=notice_right)


@app.route('/admin')
@login_required
def admin():
    return render_template('index_child.html', name='admin')


@app.route('/index')
@login_required
def index():
    if current_user:
        return render_template('index_child.html', name=current_user.dbuser['username'])
    else:
        return redirect(url_for('login'))


@app.route('/<path:path>/')
def page(path):
    page = pages.get_or_404(path)
    return render_template('page.html', page=page)


@app.route('/files/<id>', methods=['GET'])
def api_get_file(id):
    return 'you will get file id is: ' + id


@app.route('/search/<querytype>/<querystr>', methods=['GET'])
def api_search(querytype, querystr):
    if 'page' in request.args:
        page = int(request.args['page'])
    else:
        page = 0

    qtype = 'and'
    if querytype in ['or', 'and']:
        qtype = querytype

    hits, ids = searcher.search(querystr, qtype)

    paginator = Paginator(ids, num_posts_per_page)

    items = paginator[page]

    js = {
        'hits': hits,
        'pages': hits / num_posts_per_page,
        'ids': [i for i in items]
    }

    from bson import json_util

    js = json.dumps(js, default=json_util.default)

    resp = Response(js, status=200, mimetype='application/json')
    resp.headers['Access-Control-Allow-Origin'] = '*'
    return resp

def retrive_all_paths():
    watch_path = dbobjects.settings.find_one({'name': 'watch_dir'})['value']
    lines = list(
        set([path.dirname(line['file']).replace(watch_path, '').replace(sep, '') for line in dbobjects.texts.find({})]))
    return lines

@crossdomain(origin='*')
@app.route('/paths', methods=['GET'])
def api_all_path():
    lines = retrive_all_paths()
    js = json.dumps(lines, default=json_util.default)
    resp = Response(js, status=200, mimetype='application/json')
    resp.headers['Access-Control-Allow-Origin'] = '*'
    return resp

@crossdomain(origin='*')
@app.route('/richsearch/', methods=['GET'])
@app.route('/richsearch/<querytype>/', methods=['GET'])
@app.route('/richsearch/<querytype>/<querypath>/', methods=['GET'])
@app.route('/richsearch/<querytype>/<querypath>/<querystr>/', methods=['GET'])
def api_rich_search(querytype='or',querypath='*', querystr='*'):
    watch_path = dbobjects.settings.find_one({'name':'watch_dir'})['value']

    qtype = 'and'
    if querytype in ['or', 'and']:
        qtype = querytype

    lines = []

    if querystr == '*':
        all_texts = dbobjects.texts.find({})

        if querypath == '*':
            map(lambda line:lines.append({'name':line['file'].replace(watch_path,'')}), all_texts)
        else:
            for line in all_texts:
                pdf_path = path.dirname(line['file']).replace(watch_path, '').replace(sep, '')
                if querypath.lower() == pdf_path.lower():
                    lines.append({'name':line['file'].replace(watch_path,'')})
    else:
        hits, ids = searcher.search(querystr, qtype)
        for id in ids:
            line = dbobjects.texts.find_one({'_id': ObjectId(id)})
            if line:
                if querypath == '*':
                    lines.append({'name':line['file'].replace(watch_path,'')})
                else:
                    pdf_path =line['file']
                    pdf_path = path.dirname(pdf_path).replace(watch_path, '').replace(sep, '')
                    if querypath.lower() == pdf_path.lower():
                        lines.append({'name':line['file'].replace(watch_path,'')})

    js = json.dumps(lines, default=json_util.default)
    resp = Response(js, status=200, mimetype='application/json')
    resp.headers['Access-Control-Allow-Origin'] = "*"
    return resp

@crossdomain(origin='*')
@app.route('/settings/', methods=['GET','PUT'])
def api_settings():
    if request.method == 'GET':
        list = []
        map(lambda line:list.append({'name':line['name'], 'value':line['value'], 'description':line['description']}),
            [line for line in dbobjects.settings.find()])
        js = json.dumps(list, default=json_util.default)
        resp = Response(js, status=200, mimetype='application/json')
        resp.headers['Access-Control-Allow-Origin'] = '*'
        return resp
    elif request.method == 'PUT':
        print('in put method')
        result = ''
        if 'name' in request.args:
            name = request.args['name']
            if name:
                if (dbobjects.settings.find_one({'name': name})):
                    upt_result = dbobjects.settings.replace_one({'name': name}, {'value': value})
                    result = 'ok' if upt_result.matched_count == 1 else 'err'
                else:
                    result = 'err'
        else:
            result = 'err'

        js = json.dumps(result, default=json_util.default)
        resp = Response(js,
                        status=200 if result == 'ok' else 500,
                        mimetype='application/json')
        resp.headers['Access-Control-Allow-Origin'] = '*'
        return resp

@crossdomain(origin='*')
@app.route('/notices', methods=['GET','PUT'])
def api_notices():
    if request.method == 'GET':
        json_line = [{"notice_left": line['notice_left'] , "notice_right": line['notice_right'] } for line in dbobjects.notices.find()]

        js = json.dumps(json_line, default=json_util.default)
        resp = Response(js, status=200, mimetype='application/json')
        resp.headers['Access-Control-Allow-Origin'] = '*'
        return resp
    elif request.method == 'PUT':
        left_text = request.args['left_text']
        right_text = request.args['right_text']

        result = update_notices(left_text, right_text)

        js = json.dumps(result, default=json_util.default)
        resp = Response(js,
                        status=200 if result == 'ok' else 500,
                        mimetype='application/json')
        resp.headers['Access-Control-Allow-Origin'] = '*'
        return resp

def update_notices(left,right):
    if dbobjects.notices.find_one({'id': '1'}):
        upt_result = dbobjects.notices.update_one({'id':'1'}, {'notice_left':left, 'notice_right':right})
        result = 'ok' if upt_result.matched_count == 1 else 'err'
        return result
    else:
        from mongoer import inits
        inits.init_notices()
        update_notices(left,right)

    return 'can not find data with id = 1'



if __name__ == '__main__':
    # define searcher for whoosh
    searcher = pdf_whoosh.textsearch()
    searcher.build()

    app.run(host='0.0.0.0',port=9881,debug=DEBUG)